//
//  DownloadDetailViewController.swift
//  GhostWorld
//
//  Created by Kam on 2018/5/29.
//  Copyright © 2018 LKGood. All rights reserved.
//

import UIKit

private let nameCellIdentifier = "DownloadDetailNameCell"
private let opButtonsCellIdentifier = "OpButtonsCell"
private let audioCellIdentifier = "AudioTableCell"

class DownloadDetailViewController: BaseViewController {
  
  // MARK: - IBOutlets
  
  @IBOutlet private weak var tableView: UITableView!
  
  // MARK: - Private vars
  
  private var album: Album?
  private var audios: [Audio]?
  private var audioSortType: AudioSortType = .ascending
  private var isDisplayingUnDownloadedAudios = false
  
  private var rightBarButtonItem: UIBarButtonItem?
  
  // MARK: - Private methods
  
  private func getFilteredAudios() -> [Audio]? {
    // MARK: - [WARNING]: list lagging reason
    if var audios = self.audios {
      if isDisplayingUnDownloadedAudios == false {
        audios = audios.filter {
          $0.localURL != nil
        }
      }
      return audios.sorted {
        switch self.audioSortType {
        case .ascending:
          return $0.id < $1.id
        case .descending:
          return $0.id > $1.id
        }
      }
    } else {
      return nil
    }
  }
  
  private func prepareUI() {
    tableView.register(UINib(nibName: audioCellIdentifier, bundle: nil), forCellReuseIdentifier: audioCellIdentifier)
    tableView.contentInset = UIEdgeInsets.init(top: 20, left: 0, bottom: 40, right: 0)
    tableView.scrollIndicatorInsets = tableView.contentInset
  }
  
  private func setRightBarButtonItem() {
    if let notDownloadedAudios = (audios?.filter { $0.localURL == nil }),
      notDownloadedAudios.count > 0 {
      rightBarButtonItem = UIBarButtonItem (
        title: "显示全部",
        style: .plain,
        target: self,
        action: #selector(switchDisplayTypeForAllOrDownloadedAudios))
      navigationItem.rightBarButtonItem = rightBarButtonItem!
    } else {
      if rightBarButtonItem != nil {
        navigationItem.rightBarButtonItem = nil
        rightBarButtonItem = nil
      }
    }
  }
  
  @objc func switchDisplayTypeForAllOrDownloadedAudios() {
    if isDisplayingUnDownloadedAudios {
      // hide undownloaded audios
      rightBarButtonItem?.title = "显示全部"
    } else {
      // display all audios
      rightBarButtonItem?.title = "隐藏未下载"
    }
    isDisplayingUnDownloadedAudios = !isDisplayingUnDownloadedAudios
    tableView.reloadSections(IndexSet(integersIn: 1...1) , with: .automatic)
    
    if let cell = tableView.cellForRow(at: IndexPath(row: 1, section: 0)) as? DownloadOpCell {
      setDownloadAllButtonState(opCell: cell)
    }
  }
  
  private func setDownloadAllButtonState(opCell: DownloadOpCell) {
    if let notDownloadedAudios = (audios?.filter { $0.localURL == nil }),
      notDownloadedAudios.count > 0 {
      opCell.isDownloadAllButtonHidden = !isDisplayingUnDownloadedAudios
    } else {
      opCell.isDownloadAllButtonHidden = true
    }
  }
  
  private func displayLoginView() {
    let alert = UIAlertController (
      title: "尚未登录",
      message: "请登录后再加入听单",
      cancelTitle: "取消",
      cancelHandler: nil,
      confirmTitle: "登录") { _ in
        let loginViewController = UIStoryboard(name: "Account", bundle: nil).instantiateViewController(withIdentifier: "LoginViewController") as! LoginViewController
        loginViewController.addCloseButton()
        let nav = BaseNavigationController(rootViewController: loginViewController, dismissDelegate: self)
        nav.isPresentedModally = true
        self.present(nav, animated: true)
    }
    present(alert, animated: true)
  }
  
  private func addNotifications() {
    NotificationCenter.default.addObserver(self, selector: #selector(downloadFinished(notifiation:)), name: .downloadFinished, object: nil)
    NotificationCenter.default.addObserver(self, selector: #selector(streamingCacheFinished), name: .streamingCacheFinished, object: nil)
  }
  
  @objc private func downloadFinished(notifiation: Notification) {
    if let cell = tableView.cellForRow(at: IndexPath(row: 1, section: 0)) as? DownloadOpCell {
      setDownloadAllButtonState(opCell: cell)
      setRightBarButtonItem()
      isDisplayingUnDownloadedAudios = false
      tableView.reloadSections(IndexSet(integersIn: 1...1) , with: .automatic)
    }
  }
  
  @objc private func streamingCacheFinished() {
    if let cell = tableView.cellForRow(at: IndexPath(row: 1, section: 0)) as? DownloadOpCell {
      setDownloadAllButtonState(opCell: cell)
      setRightBarButtonItem()
      isDisplayingUnDownloadedAudios = false
      tableView.reloadSections(IndexSet(integersIn: 1...1) , with: .automatic)
    }
  }
  
  // MARK: - Public vars
  
  var albumIdentifier: Int = -1 {
    didSet {
      if let album = EntityManager.fetch(Album.self, fetchType: .id(albumIdentifier))?.first {
        self.album = album
      }
    }
  }
  
  // MARK: - Lifecycle
  
  override func viewDidLoad() {
    super.viewDidLoad()
    
    addNotifications()
    prepareUI()
  }
  
  override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)
    
    if let album = self.album {
      audios = album.audios
      audioSortType = AudioSortType(rawValue: Int(album.audioSortType))!
      tableView.reloadData()
      
      setRightBarButtonItem()
    }
  }
  
  override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    if segue.identifier == "ShowAddToPlayListFromDownloadedSegue" {
      let nav = segue.destination as! BaseNavigationController
      nav.dismissDelegate = self
      let addToPlayListStep1ViewController = nav.viewControllers.first as! AddToPlayListStep1ViewController
      addToPlayListStep1ViewController.audios = getFilteredAudios()
    }
  }
  
  override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
  }
  
  deinit {
    NotificationCenter.default.removeObserver(self)
  }
  
  // MARK: - IBActions
  
  
  
  // MARK: - Public methods
  
  
}

// MARK: - UITableViewDataSource

extension DownloadDetailViewController: UITableViewDataSource {
  func numberOfSections(in tableView: UITableView) -> Int {
    return 2
  }
  
  func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    switch section {
    case 0:
      return 2
    case 1:
      return getFilteredAudios()?.count ?? 0
    default:
      return 0
    }
  }
  
  func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    switch indexPath.section {
    case 0:
      if indexPath.row == 0 {
        // name cell
        let cell = tableView.dequeueReusableCell(withIdentifier: nameCellIdentifier, for: indexPath) as! DownloadDetailNameCell
        cell.nameLabel.text = album?.name ?? "未知节目"
        return cell
      } else {
        // op cell
        let cell = tableView.dequeueReusableCell(withIdentifier: opButtonsCellIdentifier, for: indexPath) as! DownloadOpCell
        cell.delegate = self
        setDownloadAllButtonState(opCell: cell)
        return cell
      }
      
    default:
      // audio cell
      let cell = tableView.dequeueReusableCell(withIdentifier: audioCellIdentifier, for: indexPath) as! AudioTableCell
      if let audio = getFilteredAudios()?[indexPath.row] {
        cell.prepare(audio: audio)
      }
      return cell
    }
  }
}

// MARK: - UITableViewDelegate

extension DownloadDetailViewController: UITableViewDelegate {
  
  func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    if indexPath.section == 1 {
      if let audio = getFilteredAudios()?[indexPath.row],
        let album = audio.album {
        NowPlayingManager.shared.update (
          audioList: getFilteredAudios(),
          audioListName: "\(album.name ?? "位置节目")-已下载",
          audioLsitType: .downloaded,
          audioListRefID: nil
        )
        NowPlayingManager.shared.play(album: album, audio: audio)
      }
    }
    
    tableView.deselectRow(at: indexPath, animated: true)
  }
  
  func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
    if indexPath.section == 1 {
      if let audio = getFilteredAudios()?[indexPath.row],
        audio.localURL != nil {
        return true
      }
    }
    return false
  }
  
  func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
    if editingStyle == .delete {
      if let audio = getFilteredAudios()?[indexPath.row],
        audio.localURL != nil {
        audio.removeCachedfile()
        if !isDisplayingUnDownloadedAudios {
          tableView.deleteRows(at: [indexPath], with: .fade)
        } else {
          tableView.reloadRows(at: [indexPath], with: .automatic)
        }
        setRightBarButtonItem()
      }
    }
  }
  
  func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
    if indexPath.section == 0 {
      if indexPath.row == 0 {
        return DownloadDetailNameCell.defaultHeight
      } else {
        return DownloadOpCell.defaultHeight
      }
    } else {
      return 60
    }
  }
}

// MARK: - DownloadOpCellDelegate

extension DownloadDetailViewController: DownloadOpCellDelegate {
  func addToPlaylist() {
    if UserManager.shared.currentUser != nil {
      performSegue(withIdentifier: "ShowAddToPlayListFromDownloadedSegue", sender: nil)
    } else {
      displayLoginView()
    }
  }
  
  func downloadAllAudios() {
    if let audios = self.audios {
      audios.forEach {
        if $0.localURL == nil && AudioDownloadManager.shared.audioIsInQueue($0) == false {
          AudioDownloadManager.shared.add(audio: $0)
        }
      }
    }
  }
  
  func sortAudios() {
    var newType: AudioSortType = .ascending
    switch audioSortType {
    case .ascending:
      newType = .descending
    case .descending:
      newType = .ascending
    }
    do {
      try album?.updateAudioSortType(newType)
      audioSortType = newType
      tableView.reloadSections(IndexSet(integersIn: 1...1) , with: .automatic)
    } catch { }
  }
}

// MARK: - BaseNavigationControllerDismissDelegate

extension DownloadDetailViewController: BaseNavigationControllerDismissDelegate {
  func dismiss(navigationController: BaseNavigationController, completion: (() -> Void)?) {
    dismiss(animated: true, completion: completion)
  }
}
